package com.prj.ufdm.web.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.prj.ufdm.web.bpo._impl.SysFunctionBPOImpl;
import com.prj.ufdm.web.bpo._impl.SysUserBPOImpl;
import com.prj.ufdm.web.security.branch.ExpAccessDeniHandleImpl;
import com.prj.ufdm.web.security.branch.ExpAuthenticationHandleImpl;
import com.prj.ufdm.web.security.branch.LoginFaiurelHandle;
import com.prj.ufdm.web.security.branch.LoginSuccessHandle;
import com.prj.ufdm.web.security.branch.TokenAuthenticationFailure;
import com.prj.ufdm.web.security.branch.TokenAuthenticationSuccess;
import com.prj.ufdm.core.util.UfdmMd5Util;

/**
 * Spring Security 权限控制（认证）
 * @author Administrator
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ScyConfig extends WebSecurityConfigurerAdapter {
	
	/**
	 *  UserDetailsService 实现类
	 */
	@Autowired
	@Qualifier("userDetailsServiceImpl")
	UserDetailsService userDetailsServiceImpl;
	
	/**
	 *  登录成功处理
	 */
	@Autowired
	@Qualifier("loginSuccessHandle")
	LoginSuccessHandle loginSuccessHandle;
	
	/**
	 *  登录失败处理
	 */
	@Autowired
	@Qualifier("loginFaiurelHandle")
	LoginFaiurelHandle loginFaiurelHandle; 
	
	/**
	 * 注销成功处理
	 */
	@Autowired
	@Qualifier("logoutSuccessProcess")
	LogoutSuccessHandler logoutSuccessProcess; 
    
	/**
	 * 身份校验异常理
	 */
	@Autowired
	ExpAuthenticationHandleImpl expAuthenticationHandleImpl;
	
	/**
	 * 访问授权异常处理
	 */
	@Autowired
	ExpAccessDeniHandleImpl expAccessDeniHandleImpl;
	
	/**
	 * TOKEN 验证成功处理
	 */
	@Autowired
	TokenAuthenticationSuccess tokenAuthenticationSuccess;
	
	/**
	 * TOKEN 验证失败处理
	 */
	@Autowired
	TokenAuthenticationFailure tokenAuthFailureHandle;
	
	@Autowired
	SysUserBPOImpl sysUserBPOImpl;
	
	@Autowired
	SysFunctionBPOImpl sysFunctionBPOImpl;
	
	/**
	 * 请求授权配置
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception 
	{
		// 禁用CSRF保护
		http
		    .csrf().disable()
				    .authorizeRequests()
				        .antMatchers(ScyConstants.AUTH_ALLLOW_URL.split(",")).permitAll()
				        .anyRequest().authenticated()
				        .and()
				    .addFilterBefore(new TokenAuthentication("/api/**",sysUserBPOImpl,sysFunctionBPOImpl,tokenAuthenticationSuccess,tokenAuthFailureHandle), BasicAuthenticationFilter.class)
				        .sessionManagement()
				        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
				        .and()
				    .formLogin()
				        .loginPage("/sysuser/login")
						.successHandler(loginSuccessHandle)
						.failureHandler(loginFaiurelHandle)
				        .and()
				     .headers()
				         .frameOptions().disable()
				         .and()
				     .logout()
				         .logoutUrl("/sysuser/logout")
				         .logoutSuccessHandler(logoutSuccessProcess)
				         .and()
				     .exceptionHandling()
				         .authenticationEntryPoint(expAuthenticationHandleImpl)
				         .accessDeniedHandler(expAccessDeniHandleImpl);
	}
	
	/**
	 * 用户名、密码验证身份
	 * @param auth
	 * @throws Exception
	 */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(new PasswordEncoder() {
	        @Override
	        public String encode(CharSequence rawPassword) {
	            return UfdmMd5Util.MD5Encode((String) rawPassword);
	        }
	        @Override
	        public boolean matches(CharSequence rawPassword, String encodedPassword) {
	            return encodedPassword.equals(UfdmMd5Util.MD5Encode((String) rawPassword));
	        }
        });
    }
    
}
